package org.example.utils;

import com.alibaba.fastjson.JSON;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import org.apache.commons.lang3.StringUtils;
import org.example.bean.SmsReturnReceiptVO;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @Author: XieHaijun
 * @Description: 阿里短信发送接口
 * @Date: Created in 9:52 2018/12/5
 * @Modified By
 */
public class SmsUtil {

    //{"bizId":"569502411457500061^0","code":"OK","message":"OK","requestId":"0C06C52E-C255-5AF0-9A47-6375473AE439"}
    public static void main(String[] args) {
        String verifyCode = "543534";
        try {
            SendSmsResponse ret = simpleSend("未木云",
                    "SMS_158345661"
                    ,"{\"code\":\""+verifyCode+"\"}",
                    null,null,13940195216L);
            System.out.println(JSON.toJSONString(ret));
        } catch (ClientException e) {
            e.printStackTrace();
        }
    }

    private static final String product = "Dysmsapi";
    private static final String domain = "dysmsapi.aliyuncs.com";

    /*private static final String accessKeyId = "LTAIZ3IVqVuxDx1f";
    private static final String accessKeySecret = "PrVIAzk2KpllEKLLPyDkdL2qbh1DVa";*/

    private static final String accessKeyId = "LTAItoWk6ozNXBS7";
    private static final String accessKeySecret = "Sg4Bj0V0xbhSMHWIvZ7kG7nhR03Ijn";

    //初始化ascClient,暂时不支持多region（请勿修改）
    private static final IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId,
            accessKeySecret);

    private static final IAcsClient acsClient;

    private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyMMdd");

    /**
     * 单次发送
     * @param signName 必填:短信签名-可在短信控制台中找到 例如 "云通信"
     * @param templateCode 必填:短信模板-可在短信控制台中找到，发送国际/港澳台消息时，请使用国际/港澳台短信模版 例如 "SMS_1000000"
     * @param templateParam 必填:最多6个字符（数字，字母）"{\"code\":\"verifyCode\"}";
     * @param smsUpExtendCode 可选-上行短信扩展码(扩展码字段控制在7位或以下，无特殊需求用户请忽略此字段) "90997"
     * @param outId 可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
     * @param phoneNumber 必填:待发送手机号。发送国际/港澳台消息时，接收号码格式为国际区号+号码，如85200000000
     */
    public static SendSmsResponse simpleSend(String signName, String templateCode, String templateParam,
                                                  String smsUpExtendCode, String outId, long phoneNumber) throws ClientException {
        SendSmsResponse ret = null;
        //String templateParam = "{\"code\":\""+verifyCode+"\"}";
        ret = send(signName,templateCode,templateParam,smsUpExtendCode,outId,String.valueOf(phoneNumber));
        return ret;
    }

    /**
     * 批量发送
     * @param signName 必填:短信签名-可在短信控制台中找到 例如 "云通信"
     * @param templateCode 必填:短信模板-可在短信控制台中找到，发送国际/港澳台消息时，请使用国际/港澳台短信模版 例如 "SMS_1000000"
     * @param templateParam 必填:最多6个字符（数字，字母）"{\"code\":\"verifyCode\"}";
     * @param smsUpExtendCode 可选-上行短信扩展码(扩展码字段控制在7位或以下，无特殊需求用户请忽略此字段) "90997"
     * @param outId 可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
     * @param phoneNumbers 必填:待发送手机号。发送国际/港澳台消息时，接收号码格式为国际区号+号码，如85200000000，多个使用,分割（最大1000个）
     */
    public static SendSmsResponse batchSend(String signName, String templateCode, String templateParam,
                                             String smsUpExtendCode, String outId, String phoneNumbers) throws ClientException {
        SendSmsResponse ret = null;
        //String templateParam = "{\"code\":\""+verifyCode+"\"}";
        ret = send(signName,templateCode,templateParam,smsUpExtendCode,outId,phoneNumbers);
        return ret;
    }

    /**
     * 根据手机号查询全部的短信回执
     * @param phoneNumber 必须：手机号（短信接收号码,如果需要查询国际短信,号码前需要带上对应国家的区号,区号的获取详见国际短信支持国家信息查询API接口）
     * @param sendDate 必须：发送短信的时间（支持最近30天记录查询）
     * @return
     */
    public static List<SmsReturnReceiptVO> querySendDetailsAll(long phoneNumber, Date sendDate){
        boolean next = true;
        int i=1;
        List<SmsReturnReceiptVO> vos = new ArrayList<>();
        do{
            List<SmsReturnReceiptVO> itemRet = querySendDetails(phoneNumber,null,sendDate,i);
            if(CollectionUtils.isEmpty(itemRet)){
                next = false;
            }else {
                vos.addAll(itemRet);
            }
            i++;
        }while (next);

        return vos;
    }

    /**
     * 查询短信发送的回执信息（部分查询，或者指定bizId的查询）
     * @param phoneNumber 必须：手机号（短信接收号码,如果需要查询国际短信,号码前需要带上对应国家的区号,区号的获取详见国际短信支持国家信息查询API接口）
     * @param bizId 可选：发送短信时的业务id（可选字段 发送流水号,从调用发送接口返回值中获取）
     * @param sendDate 必须：发送短信的时间（支持最近30天记录查询）
     * @param currentPage 必须：当前页码（从1开始）
     */
    public static List<SmsReturnReceiptVO> querySendDetails(long phoneNumber, String bizId,
                                                      Date sendDate, long currentPage){
        List<SmsReturnReceiptVO> ret = null;
        QuerySendDetailsRequest request = new QuerySendDetailsRequest();
        request.setPhoneNumber(String.valueOf(phoneNumber));
        if(StringUtils.isNotBlank(bizId)){
            request.setBizId(bizId);
        }
        if(Objects.nonNull(sendDate)){

            request.setSendDate(simpleDateFormat.format(sendDate));
        }
        request.setPageSize(50L);
        request.setCurrentPage(currentPage);
        QuerySendDetailsResponse querySendDetailsResponse = null;
        try {
            querySendDetailsResponse = acsClient.getAcsResponse(request);
        } catch (ClientException e) {
            return null;
        }
        //获取返回结果
        if(querySendDetailsResponse.getCode() != null && querySendDetailsResponse.getCode().equals("OK")){

            //代表请求成功
            List<QuerySendDetailsResponse.SmsSendDetailDTO> dataList =
                    querySendDetailsResponse.getSmsSendDetailDTOs();
            ret = new ArrayList<>();
            for(QuerySendDetailsResponse.SmsSendDetailDTO obj : dataList){
                SmsReturnReceiptVO vo = new SmsReturnReceiptVO();
                BeanUtils.copyProperties(obj,vo);
                ret.add(vo);
            }
        }
        return ret;
    }

    static {
        //设置超时时间-可自行调整
        //System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
        //System.setProperty("sun.net.client.defaultReadTimeout", "10000");
        DefaultProfile.addEndpoint( "cn-hangzhou", product, domain);
        acsClient = new DefaultAcsClient(profile);
    }

    /**
     * 发送手机短信
     * @param signName 必填:短信签名-可在短信控制台中找到 例如 "云通信"
     * @param templateCode 必填:短信模板-可在短信控制台中找到，发送国际/港澳台消息时，请使用国际/港澳台短信模版 例如 "SMS_1000000"
     * @param templateParam 可选:如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为 "{\"name\":\"Tom\", \"code\":\"123\"}"
     * @param smsUpExtendCode 可选-上行短信扩展码(扩展码字段控制在7位或以下，无特殊需求用户请忽略此字段) "90997"
     * @param outId 可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
     * @param phoneNumbers 必填:待发送手机号。支持以逗号分隔的形式进行批量调用，批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,
     *                     <br/>验证码类型的短信推荐使用单条调用的方式；发送国际/港澳台消息时，接收号码格式为国际区号+号码，如“85200000000”
     * @return
     * @throws ClientException
     */
    private static SendSmsResponse send(String signName,String templateCode,String templateParam,
                                        String smsUpExtendCode,String outId,String phoneNumbers) throws ClientException {
        SendSmsRequest request = new SendSmsRequest();
        request.setMethod(MethodType.POST);
        request.setSignName(signName);
        request.setTemplateCode(templateCode);
        if(StringUtils.isNotBlank(templateParam)){
            request.setTemplateParam(templateParam);
        }
        if(StringUtils.isNotBlank(smsUpExtendCode)){
            request.setSmsUpExtendCode(smsUpExtendCode);
        }
        if(StringUtils.isNotBlank(outId)){
            request.setOutId(outId);
        }
        request.setPhoneNumbers(phoneNumbers);
        SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
        return sendSmsResponse;
    }
}
